/**
 * @file bsp_multibuffer.c
 * @author liufeng (liufeng@injoinic.com)
 * @brief multibuffer
 * @version 0.1
 * @date 2024-12-01
 *
 * @copyright Copyright (c) 2024  injoinic
 *
 */

#include "bsp_multibuffer.h"
#include "cmsis_armclang.h"
#include "stddef.h"

/* ------------------------------------------------------------------------------------ */
/*                                       写操作API                                       */
/* ------------------------------------------------------------------------------------ */

/**
 * @brief 返回写缓冲区的地址
 * @param buffer 多缓冲区对象
 * @return uint8_t* :缓冲区已满则返回NULL，否则返回下一个缓冲区地址
 */
uint8_t* buff_write_addr(DataBuffTypedef* buffer)
{
    __disable_irq();
    //  如果缓冲区已满，则返回NULL
    if ((buffer->tail + 1) % NUM_OF_BUFF == buffer->head) {
        __enable_irq();
        return NULL;
    }
    // 否则，返回下一块待写入的缓冲区地址
    uint8_t temp = (buffer->tail + 1) % NUM_OF_BUFF;
    uint8_t* write_addr = buffer->data_buff[temp];
    __enable_irq();
    return write_addr;
}

/**
 * @brief 移动尾指针（在使用buff_write_addr函数，并接收完数据之后，调用该函数）
 * @param buffer 多缓冲区对象
 */
void buff_move_tail(DataBuffTypedef* buffer)
{
    __disable_irq();
    buffer->tail = (buffer->tail + 1) % NUM_OF_BUFF;
    __enable_irq();
}

/* ------------------------------------------------------------------------------------ */
/*                                       读操作API                                       */
/* ------------------------------------------------------------------------------------ */

/**
 * @brief 返回读缓冲区地址
 * @param buffer 多缓冲区对象
 * @return uint8_t* :缓冲区为空则返回NULL，否则返回下一个待处理的缓冲区地址
 */
uint8_t* buff_read_addr(DataBuffTypedef* buffer)
{
    __disable_irq();
    //   如果缓冲区为空，则返回NULL
    if (buffer->head == buffer->tail) {
        __enable_irq();
        return NULL;
    }
    // 否则，返回下一块待处理的缓冲区地址
    uint8_t temp = (buffer->head + 1) % NUM_OF_BUFF;
    uint8_t* read_addr = buffer->data_buff[temp];
    __enable_irq();
    return read_addr;
}

/**
 * @brief 移动头指针（在使用buff_read_addr函数，并处理完数据之后，调用该函数）
 * @param buffer 多缓冲区对象
 */
void buff_move_head(DataBuffTypedef* buffer)
{
    __disable_irq();
    buffer->head = (buffer->head + 1) % NUM_OF_BUFF;
    __enable_irq();
}

/* ------------------------------------------------------------------------------------ */
/*                                       构造函数                                        */
/* ------------------------------------------------------------------------------------ */

/**
 * @brief 多缓冲区构造函数，初始化时调用
 * @param buffer 多缓冲区对象
 */
void data_buff_construct(DataBuffTypedef* buffer)
{
    // 缓冲区清零
    for (uint8_t i = 0; i < NUM_OF_BUFF; ++i)
        for (uint8_t j = 0; j < SINGLE_BUFF_SIZE; ++j)
            buffer->data_buff[i][j] = 0;
    // 变量初始化
    buffer->head = 0;
    buffer->tail = 0;
    // 函数指针挂载
    buffer->pf_write_addr = buff_write_addr;
    buffer->pf_move_tail = buff_move_tail;

    buffer->pf_read_addr = buff_read_addr;
    buffer->pf_move_head = buff_move_head;
}
